<html lang="zh">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="jeessy2" />
    <title>DDNS-GO</title>
    <link
      class="theme"
      rel="stylesheet"
      type="text/css"
      href="./static/common.css"
    />
    <link rel="stylesheet" href="./static/bootstrap.min.css" />
    <link rel="stylesheet" href="./static/theme-button.css" />
    <script src="./static/utils.js"></script>
  </head>

  <body>
    <header>
      <div class="navbar navbar-dark bg-dark shadow-sm">
        <div class="button-container container d-flex justify-content-between">
          <a
            target="blank"
            href="https://github.com/jeessy2/ddns-go"
            class="navbar-brand d-flex align-items-center"
          >
            <strong>DDNS-GO</strong>
          </a>
          <button
            class="btn btn-info btn-sm"
            id="logsBtn"
            onclick="showHideLogs()"
          >
            日志
          </button>
          <span
            class="theme-button gg-dark-mode"
            onclick="toggleTheme(true)"
          ></span>
          <span class="badge badge-secondary">{{.Version}}</span>
        </div>
      </div>
    </header>

    <main role="main">
      <div id="mask" onclick="showHideLogs()" style="visibility: hidden"></div>
      <div class="row">
        <div class="col-md-6 offset-md-3">
          <div class="row" style="margin-top: 15px">
            <div class="col-md-4 col-sm-12">
              <button class="btn btn-primary submit_btn">Save</button>
            </div>

            <div
              class="col-md-8 col-sm-12"
              style="margin-left: auto; margin-right: 0"
            >
              <form class="form-inline" style="margin-top: 5px">
                <label for="index" style="margin-left: auto">配置切换:</label>
                <select
                  class="form-control form-control-sm"
                  style="margin: 0px 5px; width: 155px"
                  name="Index"
                  id="index"
                  value=""
                ></select>
                <button
                  class="btn btn-primary btn-sm"
                  style="margin: 0px 5px"
                  id="addBtn"
                >
                  添加
                </button>
                <button
                  class="btn btn-primary btn-sm"
                  style="margin: 0px 0px 0px 5px"
                  id="delBtn"
                >
                  删除
                </button>
              </form>
            </div>
          </div>

          <form id="formDnsConf">
            <div class="portlet">
              <h5 class="portlet__head">DNS服务商</h5>
              <div class="portlet__body">
                <div class="form-group row">
                  <label class="col-sm-2 col-form-label"></label>
                  <div class="col-sm-10">
                    <div id="DnsSelector"></div>

                    <small id="dns_help" class="form-text text-muted">
                      <a
                        target="_blank"
                        href="https://ram.console.aliyun.com/manage/ak?spm=5176.12818093.nav-right.dak.488716d0mHaMgg"
                        >创建 AccessKey</a
                      >
                    </small>
                  </div>
                </div>

                <div class="form-group row">
                  <label
                    for="DnsID"
                    id="dnsIdLabel"
                    class="col-sm-2 col-form-label"
                    >AccessKey ID</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      name="DnsID"
                      id="DnsID"
                      value=""
                    />
                  </div>
                </div>

                <div class="form-group row">
                  <label
                    for="DnsSecret"
                    id="dnsSecretLabel"
                    class="col-sm-2 col-form-label"
                    >AccessKey Secret</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      name="DnsSecret"
                      id="DnsSecret"
                      value=""
                    />
                  </div>
                </div>

                <div class="form-group row">
                  <label class="col-sm-2 col-form-label">TTL</label>
                  <div class="col-sm-10">
                    <select
                      class="form-control form"
                      name="TTL"
                      id="ttl"
                      value=""
                    >
                      <option value="" selected>自动</option>
                      <option value="1">1秒</option>
                      <option value="5">5秒</option>
                      <option value="10">10秒</option>
                      <option value="60">1分钟</option>
                      <option value="120">2分钟</option>
                      <option value="600">10分钟</option>
                      <option value="1800">30分钟</option>
                      <option value="3600">1小时</option>
                    </select>
                    <small id="ttl_help" class="form-text text-muted"
                      >如账号支持更小的 TTL，可修改。IP 有变化时才会更新
                      TTL</small
                    >
                  </div>
                </div>
              </div>
            </div>

            <div class="portlet">
              <h5 class="portlet__head">IPv4</h5>
              <div class="portlet__body">
                <div class="form-group row">
                  <label for="ipv4_enable" class="col-sm-2">是否启用</label>
                  <div class="col-sm-10">
                    <input
                      type="checkbox"
                      class="form-check-inline"
                      style="margin-top: 5px"
                      id="ipv4_enable"
                      name="Ipv4Enable"
                      checked
                    />
                  </div>
                </div>

                <div class="form-group row">
                  <label for="ipv4_url" class="col-sm-2 col-form-label"
                    >获取 IP 方式</label
                  >
                  <div class="col-sm-10">
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv4GetType"
                        id="urlRadioIpv4"
                        value="url"
                        checked
                        onclick="urlClick('ipv4')"
                      />
                      <label class="form-check-label" for="urlRadioIpv4"
                        >通过接口获取</label
                      >
                    </div>
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv4GetType"
                        id="netInterfaceRadioIpv4"
                        value="netInterface"
                        onclick="netInterfaceClick('ipv4')"
                      />
                      <label
                        class="form-check-label"
                        for="netInterfaceRadioIpv4"
                        >通过网卡获取</label
                      >
                    </div>
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv4GetType"
                        id="cmdRadioIpv4"
                        value="cmd"
                        onclick="cmdClick('ipv4')"
                      />
                      <label class="form-check-label" for="cmdRadioIpv4"
                        >通过命令获取</label
                      >
                    </div>
                    <input
                      type="url"
                      class="form-control form"
                      name="Ipv4Url"
                      id="ipv4_url"
                      aria-describedby="ipv4_url_help"
                      value="https://myip4.ipip.net, https://ddns.oray.com/checkip, https://ip.3322.net, https://4.ipw.cn"
                    />
                    <select
                      class="form-control"
                      id="ipv4_netInterface_select"
                      name="Ipv4NetInterface"
                      style="display: none"
                    ></select>
                    <input
                      type="text"
                      class="form-control form"
                      id="ipv4_cmd"
                      name="Ipv4Cmd"
                      aria-describedby="ipv4_url_help"
                      value=""
                      style="display: none"
                    />
                    <small id="ipv4_url_help" class="form-text text-muted">
                      支持多个接口，使用半角逗号分隔。如：https://myip4.ipip.net,
                      https://ddns.oray.com/checkip, https://ip.3322.net
                    </small>
                  </div>
                </div>

                <div class="form-group row">
                  <label for="ipv4_domains" class="col-sm-2 col-form-label"
                    >Domains</label
                  >
                  <div class="col-sm-10">
                    <textarea
                      class="form-control form"
                      id="ipv4_domains"
                      name="Ipv4Domains"
                      rows="3"
                      aria-describedby="ipv4_domains_help"
                    ></textarea>
                    <small id="ipv4_domains_help" class="form-text text-muted">
                      一行一个域名,
                      可使用冒号分隔根域名(example.cn.eu.org)与子域名(www),
                      填写为：<b>www:example.cn.eu.org</b>
                      <a
                        target="blank"
                        href="https://github.com/jeessy2/ddns-go/wiki/传递自定义参数"
                        >支持传递自定义参数</a
                      >
                    </small>
                  </div>
                </div>
              </div>
            </div>

            <div class="portlet">
              <h5 class="portlet__head">IPv6</h5>
              <div class="portlet__body">
                <div class="form-group row">
                  <label for="ipv6_enable" class="col-sm-2">是否启用</label>
                  <div class="col-sm-10">
                    <input
                      type="checkbox"
                      class="form-check-inline"
                      style="margin-top: 5px"
                      id="ipv6_enable"
                      name="Ipv6Enable"
                      checked
                    />
                  </div>
                </div>

                <div class="form-group row">
                  <label for="ipv6_url" class="col-sm-2 col-form-label"
                    >获取 IP 方式</label
                  >
                  <div class="col-sm-10">
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv6GetType"
                        id="urlRadioIpv6"
                        value="url"
                        checked
                        onclick="urlClick('ipv6')"
                      />
                      <label class="form-check-label" for="urlRadioIpv6"
                        >通过接口获取</label
                      >
                    </div>
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv6GetType"
                        id="netInterfaceRadioIpv6"
                        value="netInterface"
                        onclick="netInterfaceClick('ipv6')"
                      />
                      <label
                        class="form-check-label"
                        for="netInterfaceRadioIpv6"
                        >通过网卡获取</label
                      >
                    </div>
                    <div class="form-check form-check-inline">
                      <input
                        class="form-check-input"
                        type="radio"
                        name="Ipv6GetType"
                        id="cmdRadioIpv6"
                        value="cmd"
                        onclick="cmdClick('ipv6')"
                      />
                      <label class="form-check-label" for="cmdRadioIpv6"
                        >通过命令获取</label
                      >
                    </div>
                    <input
                      type="url"
                      class="form-control form"
                      id="ipv6_url"
                      name="Ipv6Url"
                      aria-describedby="ipv6_url_help"
                      value="https://speed.neu6.edu.cn/getIP.php, https://v6.ident.me, https://6.ipw.cn"
                    />
                    <select
                      class="form-control"
                      id="ipv6_netInterface_select"
                      name="Ipv6NetInterface"
                      style="display: none"
                    ></select>
                    <input
                      type="text"
                      class="form-control form"
                      id="ipv6_cmd"
                      name="Ipv6Cmd"
                      aria-describedby="ipv6_url_help"
                      value=""
                      style="display: none"
                    />
                    <small id="ipv6_url_help" class="form-text text-muted">
                      支持多个接口，使用半角逗号分隔。如：https://speed.neu6.edu.cn/getIP.php,
                      https://v6.ident.me, https://6.ipw.cn
                    </small>
                  </div>
                </div>

                <div
                  class="form-group row"
                  id="IPv6RegDiv"
                  style="display: none"
                >
                  <label for="IPv6Reg" class="col-sm-2 col-form-label"
                    >匹配正则表达式</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      name="IPv6Reg"
                      id="IPv6Reg"
                      value=""
                      aria-describedby="IPv6Reg_help"
                    />
                    <small id="IPv6Reg_help" class="form-text text-muted"
                      >可使用 @1 指定第一个IPv6地址, @2 指定第二个IPv6地址...
                      也可使用正则表达式匹配指定的IPv6地址, 留空不启用</small
                    >
                  </div>
                </div>

                <div class="form-group row">
                  <label for="ipv6_domains" class="col-sm-2 col-form-label"
                    >Domains</label
                  >
                  <div class="col-sm-10">
                    <textarea
                      class="form-control form"
                      id="ipv6_domains"
                      name="Ipv6Domains"
                      rows="3"
                      aria-describedby="ipv6_domains_help"
                    ></textarea>
                    <small id="ipv6_domains_help" class="form-text text-muted">
                      一行一个域名,
                      可使用冒号分隔根域名(example.cn.eu.org)与子域名(www),
                      填写为：<b>www:example.cn.eu.org</b>
                      <a
                        target="blank"
                        href="https://github.com/jeessy2/ddns-go/wiki/传递自定义参数"
                        >支持传递自定义参数</a
                      >
                    </small>
                  </div>
                </div>
              </div>
            </div>
          </form>

          <form id="formGlobal">
            <div class="portlet">
              <h5 class="portlet__head">其它配置</h5>
              <div class="portlet__body">
                <div class="form-group row">
                  <label for="NotAllowWanAccess" class="col-sm-2 col-form-label"
                    >禁止公网访问</label
                  >
                  <div class="col-sm-10">
                    <input
                      type="checkbox"
                      class="form-check-inline"
                      style="margin-top: 5px"
                      id="NotAllowWanAccess"
                      name="NotAllowWanAccess"
                      checked
                    />
                    <small
                      id="NotAllowWanAccess_help"
                      class="form-text text-muted"
                      >默认启用，可禁止从公网访问本页面</small
                    >
                  </div>
                </div>

                <div class="form-group row">
                  <label for="Username" class="col-sm-2 col-form-label"
                    >登录用户名</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      name="Username"
                      id="Username"
                      value=""
                      aria-describedby="Username_help"
                    />
                    <small id="Username_help" class="form-text text-muted"
                      >为保护你的信息安全，建议输入</small
                    >
                  </div>
                </div>

                <div class="form-group row">
                  <label for="Password" class="col-sm-2 col-form-label"
                    >登录密码</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      type="password"
                      name="Password"
                      id="Password"
                      value=""
                      aria-describedby="password_help"
                    />
                    <small id="password_help" class="form-text text-muted"
                      >为保护你的信息安全，建议输入</small
                    >
                  </div>
                </div>
              </div>
            </div>

            <div class="portlet">
              <h5 class="portlet__head">Webhook</h5>
              <div class="portlet__body">
                <div class="form-group row">
                  <label for="WebhookURL" class="col-sm-2 col-form-label"
                    >URL</label
                  >
                  <div class="col-sm-10">
                    <input
                      class="form-control form"
                      name="WebhookURL"
                      id="WebhookURL"
                      value=""
                      aria-describedby="WebhookURL_help"
                    />
                    <small id="WebhookURL_help" class="form-text text-muted">
                      <a
                        target="blank"
                        href="https://github.com/jeessy2/ddns-go#webhook"
                        >点击参考官方 Webhook 说明</a
                      ><br />
                      支持的变量 #{ipv4Addr}, #{ipv4Result}, #{ipv4Domains},
                      #{ipv6Addr}, #{ipv6Result}, #{ipv6Domains}
                    </small>
                  </div>
                </div>

                <div class="form-group row">
                  <label
                    for="WebhookRequestBody"
                    class="col-sm-2 col-form-label"
                    >RequestBody</label
                  >
                  <div class="col-sm-10">
                    <textarea
                      class="form-control form"
                      id="WebhookRequestBody"
                      name="WebhookRequestBody"
                      rows="3"
                      aria-describedby="WebhookRequestBody_help"
                    ></textarea>
                    <small
                      id="WebhookRequestBody_help"
                      class="form-text text-muted"
                    >
                      如 RequestBody 为空则为 GET 请求，否则为 POST
                      请求。支持的变量同上
                    </small>
                  </div>
                </div>

                <div class="form-group row">
                  <label for="WebhookHeaders" class="col-sm-2 col-form-label"
                    >Headers</label
                  >
                  <div class="col-sm-10">
                    <textarea
                      class="form-control form"
                      id="WebhookHeaders"
                      name="WebhookHeaders"
                      rows="1"
                      aria-describedby="WebhookHeaders_help"
                    ></textarea>
                    <small
                      id="WebhookHeaders_help"
                      class="form-text text-muted"
                    >
                      一行一个Header, 如：Authorization: Bearer API_KEY
                    </small>
                  </div>
                </div>

                <div class="form-group row">
                  <label class="col-sm-2 col-form-label"></label>
                  <div class="col-sm-10">
                    <button
                      class="webhook-button btn btn-primary btn-sm"
                      id="webhookTestBtn"
                      aria-describedby="webhookTestBtn_help"
                    >
                      模拟测试Webhook
                    </button>
                    <small
                      id="webhookTestBtn_help"
                      class="form-text text-muted"
                    ></small>
                  </div>
                </div>
              </div>
            </div>
          </form>

          <button
            class="btn btn-primary submit_btn"
            style="margin-bottom: 16px"
          >
            Save
          </button>
        </div>
        <div class="logs-panel col-md-6 offset-md-3" style="visibility: hidden">
          <textarea class="logs form-control" id="logs" readonly></textarea>
          <button type="button" class="btn btn-danger btn-sm" id="clearLogBtn">
            清空
          </button>
          <button
            type="button"
            class="btn btn-primary btn-sm"
            onclick="showHideLogs()"
            style="float: right"
          >
            确认
          </button>
        </div>
      </div>
    </main>
    <script>
      const dnsProviders = [
        {
          name: "Alidns(阿里云)",
          id: "alidns",
          idLabel: "AccessKey ID",
          secretLabel: "AccessKey Secret",
          helpHtml:
            "<a target='_blank' href='https://ram.console.aliyun.com/manage/ak?spm=5176.12818093.nav-right.dak.488716d0mHaMgg'>创建 AccessKey</a>",
        },
        {
          name: "腾讯云",
          id: "tencentcloud",
          idLabel: "SecretId",
          secretLabel: "SecretKey",
          helpHtml:
            "<a target='_blank' href='https://console.dnspod.cn/account/token/apikey'>创建腾讯云 API 密钥</a>",
        },
        {
          name: "DnsPod",
          id: "dnspod",
          idLabel: "ID",
          secretLabel: "Token",
          helpHtml:
            "<a target='_blank' href='https://console.dnspod.cn/account/token/token'>创建 DNSPod Token</a>",
        },
        {
          name: "Cloudflare",
          id: "cloudflare",
          idLabel: "",
          secretLabel: "Token",
          helpHtml:
            "<a target='_blank' href='https://dash.cloudflare.com/profile/api-tokens'>创建令牌->编辑区域 DNS (使用模板)</a>",
        },
        {
          name: "华为云",
          id: "huaweicloud",
          idLabel: "Access Key Id",
          secretLabel: "Secret Access Key",
          helpHtml:
            "<a target='_blank' href='https://console.huaweicloud.com/iam/?locale=zh-cn#/mine/accessKey'>新增访问密钥</a>",
        },
        {
          name: "Callback",
          id: "callback",
          idLabel: "URL",
          secretLabel: "RequestBody",
          helpHtml:
            "<a target='_blank' href='https://github.com/jeessy2/ddns-go#callback'>自定义回调</a> 支持的变量 #{ip}, #{domain}, #{recordType}, #{ttl}",
        },
        {
          name: "百度云",
          id: "baiducloud",
          idLabel: "AccessKey ID",
          secretLabel: "AccessKey Secret",
          helpHtml:
            "<a target='_blank' href='https://console.bce.baidu.com/iam/?_=1651763238057#/iam/accesslist'>创建 AccessKey</a><br /><a target='_blank' href='https://ticket.bce.baidu.com/#/ticket/create~productId=60&questionId=393&channel=2'>申请工单</a> DDNS 需调用 API ，而百度云相关 API 仅对申请用户开放，使用前请先提交工单申请。",
        },
        {
          name: "Porkbun",
          id: "porkbun",
          idLabel: "API Key",
          secretLabel: "Secret Key",
          helpHtml:
            "<a target='_blank' href='https://porkbun.com/account/api'>创建 Access</a>",
        },
        {
          name: "GoDaddy",
          id: "godaddy",
          idLabel: "Key",
          secretLabel: "Secret",
          helpHtml:
            "<a target='_blank' href='https://developer.godaddy.com/keys'>创建 API KEY</a>",
        },
        {
          name: "Google Domain",
          id: "googledomain",
          idLabel: "Username",
          secretLabel: "Password",
          helpHtml:
            "<a target='_blank' href='https://support.google.com/domains/answer/6147083?hl=zh-Hans'>新建动态域名解析记录</a>",
        },
        {
          name: "Namecheap",
          id: "namecheap",
          idLabel: "",
          secretLabel: "Password",
          helpHtml:
            "<a target='_blank' href='https://www.namecheap.com/support/knowledgebase/article.aspx/36/11/how-do-i-start-using-dynamic-dns/'>开启namecheap动态域名解析</a> <span style='color: red'>Namecheap DDNS 不支持更新 IPv6</span>",
        },
        {
          name: "NameSilo",
          id: "namesilo",
          idLabel: "",
          secretLabel: "Password",
          helpHtml:
            "<a target='_blank' href='https://www.namesilo.com/account/api-manager'>开启namesilo动态域名解析</a> <b>请注意namesilo的TTL最低1小时</b>",
        },
      ];
      let DnsSelectorInnerHTML = "";
      dnsProviders.forEach((item) => {
        DnsSelectorInnerHTML += `
      <div class="form-check form-check-inline col-form-label">
        <input class="form-check-input" type="radio" name="DnsName" id="${item.id}" value="${item.id}">
        <label class="form-check-label" for="${item.id}">
          ${item.name}
        </label>
      </div>`;
      });
      document.getElementById("DnsSelector").innerHTML = DnsSelectorInnerHTML;
      document.getElementById("alidns").checked = true;
    </script>

    <script>
      let elemValue = {};
      let elemCheck = {};
      let elemRadio = {};
      let index = -1;
      let dnsConf = [];
      const defaultConf = {
        DnsName: "alidns",
        DnsID: "",
        DnsSecret: "",
        TTL: "",
        Ipv4Enable: "on",
        Ipv4GetType: "url",
        Ipv4Url:
          "https://myip4.ipip.net,https://ddns.oray.com/checkip,https://ip.3322.net,https://4.ipw.cn",
        Ipv4Cmd: "",
        Ipv4Domains: "",
        Ipv6Enable: "on",
        Ipv6GetType: "netInterface",
        Ipv6Url:
          "https://speed.neu6.edu.cn/getIP.php,https://v6.ident.me,https://6.ipw.cn",
        Ipv6Cmd: "",
        IPv6Reg: "",
        Ipv6Domains: "",
      };

      window.addEventListener("load", () => {
        elemValue = {
          DnsID: document.getElementById("DnsID"),
          DnsSecret: document.getElementById("DnsSecret"),
          TTL: document.getElementById("ttl"),
          Ipv4Url: document.getElementById("ipv4_url"),
          Ipv4NetInterface: document.getElementById("ipv4_netInterface_select"),
          Ipv4Cmd: document.getElementById("ipv4_cmd"),
          Ipv4Domains: document.getElementById("ipv4_domains"),
          Ipv6Url: document.getElementById("ipv6_url"),
          Ipv6NetInterface: document.getElementById("ipv6_netInterface_select"),
          Ipv6Cmd: document.getElementById("ipv6_cmd"),
          IPv6Reg: document.getElementById("IPv6Reg"),
          Ipv6Domains: document.getElementById("ipv6_domains"),
        };
        elemCheck = {
          Ipv4Enable: document.getElementById("ipv4_enable"),
          Ipv6Enable: document.getElementById("ipv6_enable"),
        };
        elemRadio = {
          DnsName: {
            alidns: document.getElementById("alidns"),
            tencentcloud: document.getElementById("tencentcloud"),
            dnspod: document.getElementById("dnspod"),
            cloudflare: document.getElementById("cloudflare"),
            huaweicloud: document.getElementById("huaweicloud"),
            callback: document.getElementById("callback"),
            baiducloud: document.getElementById("baiducloud"),
            porkbun: document.getElementById("porkbun"),
            godaddy: document.getElementById("godaddy"),
            googledomain: document.getElementById("googledomain"),
            namecheap: document.getElementById("namecheap"),
            namesilo: document.getElementById("namesilo"),
          },
          Ipv4GetType: {
            url: document.getElementById("urlRadioIpv4"),
            netInterface: document.getElementById("netInterfaceRadioIpv4"),
            cmd: document.getElementById("cmdRadioIpv4"),
          },
          Ipv6GetType: {
            url: document.getElementById("urlRadioIpv6"),
            netInterface: document.getElementById("netInterfaceRadioIpv6"),
            cmd: document.getElementById("cmdRadioIpv6"),
          },
        };

        document.getElementById("NotAllowWanAccess").checked =
          "{{.NotAllowWanAccess}}" == "on";
        document.getElementById("Username").value = "{{.Username}}";
        document.getElementById("Password").value = "{{.Password}}";
        document.getElementById("WebhookURL").value = "{{.WebhookURL}}";
        document.getElementById("WebhookRequestBody").value =
          "{{.WebhookRequestBody}}";
        document.getElementById("WebhookHeaders").value = "{{.WebhookHeaders}}";
      });

      let beforeDnsID = "";

      window.addEventListener("load", () => {
        // add btn
        document.getElementById("addBtn").addEventListener("click", (e) => {
          e.preventDefault();
          // 先保存之前的
          saveConf(index);
          index = dnsConf.length;
          dnsConf[index] = defaultConf;
          // 创建新的option
          const opt = document.createElement("option");
          opt.id = "index_" + index;
          opt.value = index;
          opt.text = index;
          document.getElementById("index").appendChild(opt);
          document.getElementById("index").value = index;
          showConf(index);
        });

        // del btn
        document.getElementById("delBtn").addEventListener("click", (e) => {
          e.preventDefault();
          document.getElementById("index_" + index).disabled = true;
          document.getElementById("index_" + index).text =
            index + 1 + " - 已删除";
          dnsConf[index] = null;
          index = dnsConf.length - 1;
          for (; dnsConf[index] == null && index >= 0; index--) {}
          if (index >= 0) {
            document.getElementById("index").value = index;
            showConf(index);
          } else {
            document.getElementById("addBtn").click();
          }
        });

        // 点击加载Dns名称
        document.getElementsByName("DnsName").forEach((e) =>
          e.addEventListener("click", (e) => {
            const dnsInfo = dnsProviders.find((d) => d.id == e.target.value);
            const dnsIDElem = document.getElementById("DnsID");

            // idLabel 为空时隐藏 DnsID
            dnsIDElem.hidden = !dnsInfo.idLabel;

            if (dnsInfo.idLabel) {
              dnsIDElem.value ||= beforeDnsID;
            } else {
              beforeDnsID = dnsIDElem.value;
              dnsIDElem.value = "";
            }
            document.getElementById("dnsIdLabel").innerHTML = dnsInfo.idLabel;
            document.getElementById("dnsSecretLabel").innerHTML =
              dnsInfo.secretLabel;
            document.getElementById("dns_help").innerHTML = dnsInfo.helpHtml;
            document.getElementById("index_" + index).text =
              index + 1 + " - " + e.target.value;
          })
        );

        // 初始化DnsConf
        reloadConf("{{.DnsConf}}");
      });

      function showConf(idx) {
        const conf = dnsConf[idx] ?? {};
        for (const k in elemValue) {
          elemValue[k].value = conf[k] ?? "";
        }
        for (const k in elemCheck) {
          elemCheck[k].checked = conf[k] === "on";
        }
        for (const k in elemRadio) {
          elemRadio[k][conf[k]]?.click();
        }
      }

      function saveConf(idx) {
        const formDnsConf = new FormData(
          document.getElementById("formDnsConf")
        );
        if (idx >= 0) {
          dnsConf[idx] = Object.fromEntries(formDnsConf.entries());
        }
      }

      function reloadConf(jsonConf) {
        try {
          dnsConf = JSON.parse(jsonConf);
        } catch (e) {
          alert("解析配置失败: " + e.toString());
          return;
        }
        const selectOld = document.getElementById("index");
        const selectNew = document.createElement("select");
        selectNew.className = selectOld.className;
        selectNew.style.cssText = selectOld.style.cssText;
        selectNew.Name = selectOld.Name;
        selectNew.id = selectOld.id;
        for (let i = 0; i < dnsConf.length; i++) {
          const opt = document.createElement("option");
          opt.id = "index_" + i;
          opt.value = i;
          opt.text = i + 1 + " - " + dnsConf[i].DnsName;
          selectNew.appendChild(opt);
        }
        selectOld.parentNode.replaceChild(selectNew, selectOld);
        document.getElementById("index").addEventListener("change", (e) => {
          beforeDnsID = null; // 清空之前的，排除切换配置时使用到beforeDnsID
          saveConf(index); // 保存当前值
          index = parseInt(e.target.value);
          showConf(index); // 加载新选择的值
        });
        index =
          index < dnsConf.length && index >= 0 ? index : dnsConf.length - 1;
        if (dnsConf.length > 0) {
          document.getElementById("index").value = index;
          showConf(index);
        } else {
          document.getElementById("addBtn").click();
        }
      }
    </script>

    <script>
      window.addEventListener("load", () => {
        document.querySelectorAll(".submit_btn").forEach((button) =>
          button.addEventListener("click", (e) => {
            // save config
            saveConf(index);
            let data2Save = new FormData(document.getElementById("formGlobal"));
            data2Save.append("DnsConf", JSON.stringify(dnsConf));
            // fetch
            fetch("./save", {
              method: "POST",
              body: data2Save,
            })
              .then((r) => r.text())
              .then((resp) => {
                const respJson = JSON.parse(resp);
                if (respJson.result !== "ok") {
                  showMessage({
                    content: respJson.result,
                    type: "error",
                    duration: 5000,
                  });
                } else {
                  showMessage({
                    content: "保存成功",
                    type: "success",
                    duration: 1500,
                  });
                  reloadConf(respJson.dnsConf);
                }
              })
              .catch((err) => {
                alert(`保存失败: ${err.toString()}`);
              });
          })
        );
      });
    </script>

    <script>
      function getLogs(loop = false) {
        fetch("./logs")
          .then((res) => res.text())
          .then((result) => {
            const logsList = JSON.parse(result);
            const logsDom = document.getElementById("logs");
            // 判断滚动条是否在底部
            const isBottom =
              logsDom.scrollHeight - logsDom.scrollTop - logsDom.clientHeight <
              10;
            logsDom.value = logsList.join("");
            // 如果滚动条原先在底部，滚动到底部
            if (isBottom) {
              logsDom.scrollTop = logsDom.scrollHeight;
            }
            const oldLogItem = localStorage.getItem("logItem") || "";
            localStorage.setItem(
              "logItem",
              logsList[logsList.length - 1] || ""
            );
            // 计算日志更新部分
            const newLogsList = logsList.slice(
              logsList.indexOf(oldLogItem) + 1
            );
            // 如果日志有更新且当前未读到，增加未读标记
            if (
              newLogsList.length &&
              document.querySelector(".logs-panel").style.visibility ===
                "hidden"
            ) {
              document.getElementById("logsBtn").classList.add("unread"); // 没有分号会导致和下面合并为同一个语句
              // 如果新增日志行数小于等于3，则message显示新增日志，否则显示前2行并提示剩余行数
              (async () => {
                if (newLogsList.length <= 3) {
                  for (const line of newLogsList) {
                    showMessage({
                      type: "info",
                      content: line,
                    });
                    await delay(800);
                  }
                } else {
                  for (const line of newLogsList.slice(0, 2)) {
                    showMessage({
                      type: "info",
                      content: line,
                    });
                    await delay(800);
                  }
                  showMessage({
                    type: "info",
                    content: `剩余${newLogsList.length - 2}条日志请自行查看`,
                  });
                }
              })();
            }
          })
          .finally(() => {
            if (loop) {
              setTimeout(getLogs, 5 * 1000, true);
            }
          });
      }

      window.addEventListener("load", () => {
        getLogs(true);
        document
          .getElementById("clearLogBtn")
          .addEventListener("click", (e) => {
            e.preventDefault();
            fetch("./clearLog")
              .then(() => {
                getLogs();
              })
              .catch((err) => {
                alert(err.toString());
              });
          });
      });
    </script>

    <script>
      function displayElement(label, show_label) {
        const suffixes = ["netInterface_select", "url", "cmd"];
        for (const suffix of suffixes) {
          document.getElementById(`${label}_${suffix}`).style.display =
            suffix === show_label ? "block" : "none";
        }
      }

      // 点击接口获取
      function urlClick(label) {
        displayElement(label, "url");

        if (label === "ipv4") {
          document.getElementById("ipv4_url_help").innerText =
            "支持多个接口，使用半角逗号分隔。如：https://myip4.ipip.net, https://ddns.oray.com/checkip, https://ip.3322.net";
        } else {
          document.getElementById("ipv6_url_help").innerText =
            "支持多个接口，使用半角逗号分隔。如：https://speed.neu6.edu.cn/getIP.php, https://v6.ident.me, https://6.ipw.cn";
          document.getElementById("IPv6RegDiv").style.display = "none";
        }
      }

      // 点击网卡获取
      function netInterfaceClick(label) {
        displayElement(label, "netInterface_select");
        if (label === "ipv4") {
          document.getElementById("ipv4_url_help").innerText =
            "通过网卡获取 IP，建议在多宽带的路由器中使用";
        } else {
          document.getElementById("ipv6_url_help").innerText =
            "通过网卡获取 IP，如不指定匹配正则表达式，将默认使用第一个 IPv6 地址";
          document.getElementById("IPv6RegDiv").removeAttribute("style");
        }

        fetch(`./${label}NetInterface`)
          .then((res) => res.text())
          .then((result) => {
            if (result) {
              const interfaces = JSON.parse(result);

              const df = new DocumentFragment();
              for (const interface of interfaces) {
                const option = document.createElement("option");
                option.value = interface.Name;
                option.innerText = `${interface.Name}(${interface.Address.join(
                  ", "
                )})`;
                df.appendChild(option);
              }
              const selectElement = document.getElementById(
                `${label}_netInterface_select`
              );
              while (selectElement.lastChild) {
                selectElement.removeChild(selectElement.lastChild);
              }
              document
                .getElementById(`${label}_netInterface_select`)
                .appendChild(df);
              // 选中已保存的IPv4网卡
              if (label === "ipv4") {
                document.getElementById(`${label}_netInterface_select`).value =
                  dnsConf[index].Ipv4NetInterface
                    ? dnsConf[index].Ipv4NetInterface
                    : interfaces[0].Name;
              }
              // 选中已保存的IPv6网卡
              if (label === "ipv6") {
                document.getElementById(`${label}_netInterface_select`).value =
                  dnsConf[index].Ipv6NetInterface
                    ? dnsConf[index].Ipv6NetInterface
                    : interfaces[0].Name;
              }
            } else {
              document.getElementById(`${label}_url_help`).innerHTML =
                '<span style="color: red">没有找到可用的网卡</span>';
            }
          });
      }

      // 通过命令获取
      function cmdClick(label) {
        const warning = "警告：执行的命令拥有本服务所具有的权限，请谨慎使用！";
        displayElement(label, "cmd");
        if (label === "ipv4") {
          document.getElementById("ipv4_url_help").innerHTML = `<p>
          通过命令获取 IP，仅使用标准输出（stdout）的第一个匹配的 IPv4 地址。如：ip -4 addr show eth1
          <a target="blank" href="https://github.com/jeessy2/ddns-go/wiki/通过命令获取IP参考">点击参考更多</a>
          <br /><strong>${warning}</strong>
          </p>`;
        } else {
          document.getElementById("ipv6_url_help").innerHTML = `<p>
          通过命令获取 IP，仅使用标准输出（stdout）的第一个匹配的 IPv6 地址。如：ip -6 addr show eth1
          <a target="blank" href="https://github.com/jeessy2/ddns-go/wiki/通过命令获取IP参考">点击参考更多</a>
          <br /><strong>${warning}</strong>
          </p>`;
          document.getElementById("IPv6RegDiv").style.display = "none";
        }
      }
    </script>
    <script>
      window.addEventListener("load", () => {
        const theme =
          localStorage.getItem("theme") ??
          (window.matchMedia("(prefers-color-scheme: dark)").matches
            ? "dark"
            : "light");

        if (theme === "dark") {
          toggleTheme();
        }

        document
          .getElementById("webhookTestBtn")
          .addEventListener("click", (e) => {
            e.preventDefault();
            const formData = new FormData();
            formData.append("URL", document.getElementById("WebhookURL").value);
            formData.append(
              "RequestBody",
              document.getElementById("WebhookRequestBody").value
            );
            formData.append(
              "WebhookHeaders",
              document.getElementById("WebhookHeaders").value
            );
            fetch("./webhookTest", {
              method: "POST",
              body: formData,
            })
              .then(() => {
                const webhookTestBtnHelp = document.getElementById(
                  "webhookTestBtn_help"
                );
                webhookTestBtnHelp.innerText =
                  "提交模拟测试成功! 数据为假数据, 只是为了测试Webhook正常与否";
                setTimeout(() => {
                  webhookTestBtnHelp.innerText = "";
                }, 5000);
              })
              .catch((err) => {
                alert(err.toString());
              });
          });
      });
    </script>

    <script>
      function toggleTheme(write = false) {
        const docEle = document.documentElement;
        if (docEle.getAttribute("data-theme") === "dark") {
          docEle.removeAttribute("data-theme");
          write && localStorage.setItem("theme", "light");
        } else {
          docEle.setAttribute("data-theme", "dark");
          write && localStorage.setItem("theme", "dark");
        }
      }

      function showHideLogs() {
        // 取消未读标记
        document.getElementById("logsBtn").classList.remove("unread");
        const logsPanel = document.querySelector(".logs-panel");
        const maskEle = document.querySelector("#mask");
        if (logsPanel.style.visibility === "hidden") {
          logsPanel.style.visibility = "";
          maskEle.style.visibility = "";
        } else {
          logsPanel.style.visibility = "hidden";
          maskEle.style.visibility = "hidden";
        }
      }
    </script>
  </body>
</html>
